#ifndef __WIZ_UTILS_EVENT_SAFE_TEMPLATE_HPP__SHANHAOBO_19800429__
#define __WIZ_UTILS_EVENT_SAFE_TEMPLATE_HPP__SHANHAOBO_19800429__

#include "../../Base/WizBase.hpp"
#include "../../Core/Container/WizDataTypeMap.hpp"
#include "../../Core/Container/WizDataTypeMultiMap.hpp"

#include "../../DataType/Signal/WizDataTypeSignal.hpp"

namespace Wiz
{
    namespace Event
    {
        namespace Safe
        {
            namespace Agency
            {
                template <class ParamT> class Type;
            } /// end of namespace Agency

            namespace Community
            {
                namespace Node
                {
                    template <class ParamT> class Type;
                } /// end of namespace Node
                template <class ParamT> class Type;
            } /// end of namespace Community

            namespace Transfer
            {
                namespace Node
                {
                    template <class ParamT> class Type;
                } /// end of namespace Node
                template <class ParamT> class Type;
            } /// end of namespace Transfer

            namespace Publisher
            {
                template <class ParamT> class Type;
            } /// end of namespace Publisher

            namespace Subscriber
            {
                template <class ParamT> class Type;
            } /// end of namespace Subscriber

            template <class ParamT> class Type;
        } /// end of namespace Safe
    } /// end of namespace Event
} /// end of namespace Wiz

#endif /*__WIZ_UTILS_EVENT_SAFE_TEMPLATE_HPP__SHANHAOBO_19800429__*/


#if defined(WIZ_EVENT_PARAM_COUNT) && (WIZ_EVENT_PARAM_COUNT >= 0) && (WIZ_EVENT_PARAM_COUNT < 255)

namespace Wiz
{
    namespace Event
    {
        namespace Safe
        {
            namespace Subscriber
            {
                template <class EvtT WIZ_COMMA_IF(WIZ_EVENT_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, class T)>
                class Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))> : private ::Wiz::Signal::Safe::Object::Type<::Wiz::Void::Type(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>
                {
                    typedef typename ::Wiz::Signal::Safe::Object::Type<::Wiz::Void::Type(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))> tSuper;
                public:
                    Type() : tSuper()
                    {}
                public:
                    virtual ::Wiz::Void::Type EventRespond(WIZ_ENUM_PARAM_XY(WIZ_EVENT_PARAM_COUNT, T, A))
                    {
                    }
                };
            } /// end of namespace Subscriber

            namespace Publisher
            {
                template <class EvtT WIZ_COMMA_IF(WIZ_EVENT_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, class T)>
                class Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))> : private ::Wiz::Signal::Safe::Type<::Wiz::Void::Type(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>
                {
                    typedef typename ::Wiz::Signal::Safe::Type<::Wiz::Void::Type(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>   tSuper;
                public:
                    typedef typename ::Wiz::Event::Safe::Subscriber::Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>     tSubscriber;
                public:
                    Type() : tSuper()
                    {}
                public:
                    ::Wiz::Void::Type EventPublish(WIZ_ENUM_PARAM_XY(WIZ_EVENT_PARAM_COUNT, T, A))
                    {
                        tSuper::SignalExecute(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, A));
                    }
                public:
                    ::Wiz::Void::Type Subscribe(const tSubscriber* SPtr)
                    {
                        tSuper::Register(SPtr, &tSubscriber::EventRespond);
                    }
                    ::Wiz::Void::Type Unsubscribe(const tSubscriber* SPtr)
                    {
                        tSuper::Unregister(SPtr, &tSubscriber::EventRespond);
                    }
                public:
                    template<class U>
                    ::Wiz::Void::Type Subscribe(const U* SPtr, ::Wiz::Void::Type(U::*FP)(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T)))
                    {
                        tSuper::Register(SPtr, FP);
                    }
                    template<class U>
                    ::Wiz::Void::Type Unsubscribe(const U* SPtr, ::Wiz::Void::Type(U::*FP)(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T)))
                    {
                        tSuper::Unregister(SPtr, FP);
                    }
                };
            } /// end of namespace Publisher

            namespace Agency
            {
                template <class EvtT WIZ_COMMA_IF(WIZ_EVENT_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, class T)>
                class Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>
                {
                public:
                    typedef typename ::Wiz::Event::Safe::Publisher::Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>    tPublisher;
                    typedef typename tPublisher::tSubscriber                                                            tSubscriber;
                public:
                    typedef ::Wiz::MultiMap::Type<EvtT, tPublisher*>                                                    tPublisherMap;
                protected:
                    tPublisherMap m_PublisherMap;
                public:
                    Type()
                    {}
                public:
                    ::Wiz::Void::Type Register(const EvtT& E, tPublisher* PPtr)
                    {
                        WIZ_ASSERT(::Wiz::IsValidPtr(PPtr));
                        m_PublisherMap.Insert(E, PPtr);
                    }
                    ::Wiz::Void::Type Unregister(const EvtT& E, tPublisher* PPtr)
                    {
                        WIZ_ASSERT(::Wiz::IsValidPtr(PPtr));
                        tPublisherMap::tIterator Itr = m_PublisherMap.LowerBound(E);
                        tPublisherMap::tIteratorConst ItrEnd = m_PublisherMap.UpperBound(E);
                        for (; Itr != ItrEnd; Itr++)
                        {
                            if (Itr.GetValue() == PPtr)
                            {
                                m_PublisherMap.Erase(Itr);
                                return;
                            }
                        }
                    }
                public:
                    ::Wiz::Void::Type Subscribe(const EvtT& E, const tSubscriber* SPtr)
                    {
                        this->Subscribe(E, SPtr, &tSubscriber::EventRespond);
                    }
                    ::Wiz::Void::Type Unsubscribe(const EvtT& E, const tSubscriber* SPtr)
                    {
                        this->Unsubscribe(E, SPtr, &tSubscriber::EventRespond);
                    }
                public:
                    template<class U>
                    ::Wiz::Void::Type Subscribe(const EvtT& E, const U* C, ::Wiz::Void::Type(U::*FP)(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T)))
                    {
                        WIZ_ASSERT(::Wiz::IsValidPtr(C));
                        tPublisherMap::tIterator Found = m_PublisherMap.Find(E);
                        if (Found != m_PublisherMap.End())
                        {
                            Found.GetValue()->Register(C, FP);
                        }
                    }
                    template<class U>
                    ::Wiz::Void::Type Unsubscribe(const EvtT& E, const U* C, ::Wiz::Void::Type(U::*FP)(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T)))
                    {
                        WIZ_ASSERT(::Wiz::IsValidPtr(C));
                        tPublisherMap::tIterator Found = m_PublisherMap.Find(E);
                        if (Found != m_PublisherMap.End())
                        {
                            Found.GetValue()->Unregister(C, FP);
                        }
                    }
                };
            } /// end of namespace Agency

            namespace Community
            {
                namespace Node
                {
                    template <class EvtT WIZ_COMMA_IF(WIZ_EVENT_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, class T)>
                    class Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))> : public ::Wiz::Event::Safe::Subscriber::Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>
                    {
                    public:
                        typedef typename ::Wiz::Event::Safe::Publisher::Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))> tPublisher;
                        typedef typename tPublisher::tSubscriber tSubscriber;
                    protected:
                        tPublisher m_Publisher;
                    public:
                        Type()
                        {}
                    public:
                        ::Wiz::Void::Type Subscribe(const tSubscriber* SPtr)
                        {
                            WIZ_ASSERT(::Wiz::IsValidPtr(SPtr));
                            m_Publisher.Subscribe(SPtr);
                        }
                        ::Wiz::Void::Type Unsubscribe(const tSubscriber* SPtr)
                        {
                            WIZ_ASSERT(::Wiz::IsValidPtr(SPtr));
                            m_Publisher.Unsubscribe(SPtr);
                        }
                    public:
                        template<class U>
                        ::Wiz::Void::Type Subscribe(const U* C, ::Wiz::Void::Type(U::*FP)(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T)))
                        {
                            WIZ_ASSERT(::Wiz::IsValidPtr(C));
                            m_Publisher.Subscribe(C, FP);
                        }
                        template<class U>
                        ::Wiz::Void::Type Unsubscribe(const U* C, ::Wiz::Void::Type(U::*FP)(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T)))
                        {
                            WIZ_ASSERT(::Wiz::IsValidPtr(C));
                            m_Publisher.Unsubscribe(C, FP);
                        }
                    public:
                        virtual ::Wiz::Void::Type EventPublish(WIZ_ENUM_PARAM_XY(WIZ_EVENT_PARAM_COUNT, T, A))
                        {
                            m_Publisher.EventPublish(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, A));
                        }
                    };
                } /// end of namespace Node

                template <class EvtT WIZ_COMMA_IF(WIZ_EVENT_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, class T)>
                class Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>
                {
                public:
                    typedef typename ::Wiz::Event::Safe::Agency::Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>           tSuper;
                    typedef typename ::Wiz::Event::Safe::Publisher::Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>        tPublisher;
                    typedef typename ::Wiz::Event::Safe::Community::Node::Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>   tNode;
                    typedef typename tPublisher::tSubscriber                                                                tSubscriber;
                protected:
                    typedef ::Wiz::Map::Type<EvtT, tNode>                                                                   tNodeMap;
                    tNodeMap m_NodeMap;
                public:
                    Type(){}
                public:
                    ::Wiz::Void::Type Subscribe(const EvtT& E, const tSubscriber* SPtr)
                    {
                        this->Subscribe(E, SPtr, &tSubscriber::EventRespond);
                    }
                    ::Wiz::Void::Type Unsubscribe(const EvtT& E, const tSubscriber* SPtr)
                    {
                        this->Unsubscribe(E, SPtr, &tSubscriber::EventRespond);
                    }
                public:
                    template<class U>
                    ::Wiz::Void::Type Subscribe(const EvtT& E, const U* C, ::Wiz::Void::Type(U::*FP)(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T)))
                    {
                        WIZ_ASSERT(::Wiz::IsValidPtr(C));
                        tNodeMap::tIterator Found = m_NodeMap.Find(E);
                        if (Found == m_NodeMap.End())
                        {
                            Found = m_NodeMap.Insert(E, tNode());
                        }

                        Found.GetValue().Subscribe(C, FP);
                    }
                    template<class U>
                    ::Wiz::Void::Type Unsubscribe(const EvtT& E, const U* C, ::Wiz::Void::Type(U::*FP)(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T)))
                    {
                        WIZ_ASSERT(::Wiz::IsValidPtr(C));
                        tNodeMap::tIterator Found = m_NodeMap.Find(E);
                        if (Found != m_NodeMap.End())
                        {
                            Found.GetValue().Unsubscribe(C, FP);
                        }
                    }
                public:
                    ::Wiz::Void::Type EventPublish(const EvtT& E WIZ_COMMA_IF(WIZ_EVENT_PARAM_COUNT) WIZ_ENUM_PARAM_XY(WIZ_EVENT_PARAM_COUNT, T, A))
                    {
                        tNodeMap::tIterator Found = m_NodeMap.Find(E);
                        if (Found != m_NodeMap.End())
                        {
                            Found.GetValue().EventPublish(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, A));
                        }
                    }
                };
            } /// end of namespace Community

            namespace Transfer
            {
                namespace Node
                {
                    template <class EvtT WIZ_COMMA_IF(WIZ_EVENT_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, class T)>
                    class Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))> : public ::Wiz::Event::Safe::Subscriber::Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>
                    {
                    public:
                        typedef typename ::Wiz::Event::Safe::Publisher::Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>    tPublisher;
                        typedef typename tPublisher::tSubscriber                                                            tSubscriber;
                    protected:
                        tPublisher m_Publisher;
                    public:
                        Type()
                        {}
                    public:
                        ::Wiz::Void::Type Subscribe(const tSubscriber* SPtr)
                        {
                            m_Publisher.Subscribe(SPtr);
                        }
                        ::Wiz::Void::Type Unsubscribe(const tSubscriber* SPtr)
                        {
                            m_Publisher.Unsubscribe(SPtr);
                        }
                    public:
                        template<class U>
                        ::Wiz::Void::Type Subscribe(const U* C, ::Wiz::Void::Type(U::*FP)(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T)))
                        {
                            WIZ_ASSERT(::Wiz::IsValidPtr(C));
                            m_Publisher.Subscribe(C, FP);
                        }
                        template<class U>
                        ::Wiz::Void::Type Unsubscribe(const U* C, ::Wiz::Void::Type(U::*FP)(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T)))
                        {
                            WIZ_ASSERT(::Wiz::IsValidPtr(C));
                            m_Publisher.Unsubscribe(C, FP);
                        }
                    public:
                        virtual ::Wiz::Void::Type EventRespond(WIZ_ENUM_PARAM_XY(WIZ_EVENT_PARAM_COUNT, T, A))
                        {
                            m_Publisher.EventPublish(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, A));
                        }
                    };
                } /// end of namespace Node

                template <class EvtT WIZ_COMMA_IF(WIZ_EVENT_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, class T)>
                class Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>
                {
                public:
                    typedef typename ::Wiz::Event::Safe::Agency::Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>         tSuper;
                    typedef typename ::Wiz::Event::Safe::Publisher::Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>      tPublisher;
                    typedef typename ::Wiz::Event::Safe::Transfer::Node::Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))> tNode;
                    typedef typename tPublisher::tSubscriber                                                                    tSubscriber;
                    typedef ::Wiz::MultiMap::Type<EvtT, tPublisher*>                                                            tPublisherMap;
                    typedef ::Wiz::Map::Type<EvtT, tNode>                                                                       tNodeMap;
                public:
                    tPublisherMap& GetPubliserMap()
                    {
                        return m_PublisherMap;
                    }
                public:
                    Type()
                    {}
                public:
                    ::Wiz::Void::Type Register(const EvtT& E, tPublisher* PPtr)
                    {
                        WIZ_ASSERT(::Wiz::IsValidPtr(PPtr));
                        tNodeMap::tIterator Found = m_NodeMap.Find(E);
                        if (Found == m_NodeMap.End())
                        {
                            Found = m_NodeMap.Insert(E, tNode());
                        }

                        PPtr->Subscribe(&(Found.GetValue()));
                        m_PublisherMap.Insert(E, PPtr);
                    }
                    ::Wiz::Void::Type Unregister(const EvtT& E, tPublisher* PPtr)
                    {
                        WIZ_ASSERT(::Wiz::IsValidPtr(PPtr));
                        tNodeMap::tIteratorConst FoundNode = m_NodeMap.Find(E);
                        if (FoundNode != m_NodeMap.End())
                        {
                            tPublisherMap::tIterator Itr = m_PublisherMap.LowerBound(E);
                            tPublisherMap::tIteratorConst ItrEnd = m_PublisherMap.UpperBound(E);
                            for (; Itr != ItrEnd; Itr++)
                            {
                                if (Itr.GetValue() == PPtr)
                                {
                                    PPtr->Unsubscribe(&(FoundNode.GetValue()));
                                    m_PublisherMap.Erase(Itr);
                                    return;
                                }
                            }
                        }
                    }
                public:
                    ::Wiz::Void::Type Subscribe(const EvtT& E, const tSubscriber* SPtr)
                    {
                        this->Subscribe(E, SPtr, &tSubscriber::EventRespond);
                    }
                    ::Wiz::Void::Type Unsubscribe(const EvtT& E, const tSubscriber* SPtr)
                    {
                        this->Unsubscribe(E, SPtr, &tSubscriber::EventRespond);
                    }
                public:
                    template<class U>
                    ::Wiz::Void::Type Subscribe(const EvtT& E, const U* SPtr, ::Wiz::Void::Type(U::*FP)(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T)))
                    {
                        WIZ_ASSERT(::Wiz::IsValidPtr(SPtr));
                        tNodeMap::tIterator Found = m_NodeMap.Find(E);
                        if (Found == m_NodeMap.End())
                        {
                            Found = m_NodeMap.Insert(E, tNode());
                        }
                        Found.GetValue().Subscribe(SPtr, FP);
                    }
                    template<class U>
                    ::Wiz::Void::Type Unsubscribe(const EvtT& E, const U* SPtr, ::Wiz::Void::Type(U::*FP)(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T)))
                    {
                        WIZ_ASSERT(::Wiz::IsValidPtr(SPtr));
                        tNodeMap::tIterator Found = m_NodeMap.Find(E);
                        if (Found != m_NodeMap.End())
                        {
                            Found.GetValue().Unsubscribe(SPtr, FP);
                        }
                    }
                public:
                    ::Wiz::Void::Type Receive(const EvtT& E WIZ_COMMA_IF(WIZ_EVENT_PARAM_COUNT) WIZ_ENUM_PARAM_XY(WIZ_EVENT_PARAM_COUNT, T, A))
                    {
                        tNodeMap::tIterator Found = m_NodeMap.Find(E);
                        if (Found != m_NodeMap.End())
                        {
                            Found.GetValue().EventRespond(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, A));
                        }
                    }
                    ::Wiz::Void::Type EventPublish(const EvtT& E WIZ_COMMA_IF(WIZ_EVENT_PARAM_COUNT) WIZ_ENUM_PARAM_XY(WIZ_EVENT_PARAM_COUNT, T, A))
                    {
                        tPublisher* TempPtr;
                        tPublisherMap::tIterator Lower = m_PublisherMap.LowerBound(E);
                        tPublisherMap::tIteratorConst Upper = m_PublisherMap.UpperBound(E);
                        for (; Lower != Upper; Lower++)
                        {
                            TempPtr = Lower.GetValue();
                            WIZ_ASSERT(::Wiz::IsValidPtr(TempPtr));
                            (*TempPtr).EventPublish(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, A));
                        }
                    }
                protected:
                    tPublisherMap   m_PublisherMap;
                    tNodeMap        m_NodeMap;
                };
            } /// end of namespace Transfer

            template <class EvtT WIZ_COMMA_IF(WIZ_EVENT_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, class T)>
            struct Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>
            {
                typedef typename ::Wiz::Event::Safe::Publisher::Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>    tPublisher;
                typedef typename ::Wiz::Event::Safe::Subscriber::Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>   tSubscriber;
                typedef typename ::Wiz::Event::Safe::Agency::Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>       tAgency;
                typedef typename ::Wiz::Event::Safe::Community::Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>    tCommunity;
                typedef typename ::Wiz::Event::Safe::Transfer::Type<EvtT(WIZ_ENUM_PARAM_X(WIZ_EVENT_PARAM_COUNT, T))>     tTransfer;
            };
        } /// end of namespace Safe
    } /// end of namespace Event
} /// end of namespace Wiz


#endif /* defined(WIZ_EVENT_PARAM_COUNT) && (WIZ_EVENT_PARAM_COUNT >= 0) && (WIZ_EVENT_PARAM_COUNT < 255)*/

